package com.gopay.common.dss.tools.impl;

import com.gopay.common.cps.dao.global.GopayGlobalVariablesDao;
import com.gopay.common.domain.global.GopayGlobalVariables;
import com.gopay.common.dss.tools.FuseTool;
import com.gopay.common.util.IPV4Util;
import com.gopay.sms.client.GopaySMSHttpClient;
import com.gopay.sms.common.constants.SMSAppId;
import com.gopay.sms.common.domain.RequestVO;
import com.gopay.sms.common.domain.ResponseVO;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by zhaojt on 2017/7/28.
 * 熔断器
 */
@Component("fuseTool")
public class FuseToolImpl implements FuseTool{

    private Logger logger = LoggerFactory.getLogger(FuseToolImpl.class);
    private ConcurrentHashMap<String, Integer> fuseTimesCounters = new ConcurrentHashMap<>();

    @Resource(name = "gopayGlobalVariablesDao")
    private GopayGlobalVariablesDao gopayGlobalVariablesDao;

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public synchronized boolean fuse(String switchkKey, String mobileKey, int maxFuseTimes){
        Integer counter = fuseTimesCounters.get(switchkKey);
        if(counter == null){
            fuseTimesCounters.put(switchkKey, new Integer(1));
        }else {
            fuseTimesCounters.put(switchkKey, new Integer(counter.intValue() + 1));
        }

        //熔断次数大于等于最大熔断次数，进行熔断并通知
        if(fuseTimesCounters.get(switchkKey).compareTo(maxFuseTimes) >= 0){

            doFuse(switchkKey, mobileKey);
            //将缓存中的计数删除
            fuseTimesCounters.remove(switchkKey);

            return true; //到达最大熔断次数，进行了熔断
        }

        return false;//未到熔断次数
    }


    /**
     * 将对应switchKey开关设置为关闭，如果有配置对应负责人手机号，进行短信通知!
     * @param switchKey
     * @param mobileKey
     */
    private void doFuse(String switchKey, String mobileKey){
        logger.info(switchKey + "开关熔断开始！！！！！");
        // 控制开关
        Map<String, Object> params = new HashMap<>();
        params.put("paramKey", switchKey);
        List gopayGlobalVariablesList= gopayGlobalVariablesDao.getGopayGlobalVariablesList(params);
        int switchVal = 0;
        if(gopayGlobalVariablesList != null && gopayGlobalVariablesList.size() > 0){
            try{
                GopayGlobalVariables gopayGlobalVariables = (GopayGlobalVariables)gopayGlobalVariablesList.get(0);
                if("1".equals(gopayGlobalVariables.getParamValue())){
                    switchVal = 1;
                }
                gopayGlobalVariables.setParamValue("0");//设置关闭缓存
                gopayGlobalVariablesDao.update(gopayGlobalVariables);
            }catch (Exception e){
                logger.error( "修改"+ switchKey + "熔断开关异常：" + e.getMessage());
            }finally {
                try{
                    sendSmsMsg(switchKey, mobileKey, params, switchVal);
                }catch (Exception ex){
                    logger.error("发送熔断短信异常，异常信息：", ex);
                }
            }
        }
        logger.info(switchKey +"开关熔断结束！！！！！");
    }


    private void sendSmsMsg(String switchKey, String mobileKey, Map params, int switchVal){
        //发送短信
        if(StringUtils.isNotBlank(mobileKey)) {
            params.put("paramKey", mobileKey);
            List gopayGlobalVariables = gopayGlobalVariablesDao.getGopayGlobalVariablesList(params);

            if (gopayGlobalVariables != null && gopayGlobalVariables.size() > 0) {
                GopayGlobalVariables mobileVar = (GopayGlobalVariables) gopayGlobalVariables.get(0);

                if (StringUtils.isNotEmpty(mobileVar.getParamValue())) {
                    if(switchVal == 1) {
                        RequestVO req = new RequestVO();
                        req.setAppId(SMSAppId._90000.value);
                        req.setMobile(mobileVar.getParamValue());// 电话号码(多个以逗号分隔)

                        if (StringUtils.isNotBlank(mobileVar.getRemark())) {
                            req.setContent(mobileVar.getRemark() + "，请排查原因。 IP:" + IPV4Util.getIpv4());
                        } else {
                            req.setContent(switchKey + "开关已熔断，请请排查原因! IP:" + IPV4Util.getIpv4());
                        }

                        logger.info("开始发送" + switchKey + "开关熔断短信!");
                        ResponseVO resp = GopaySMSHttpClient.getInstance().createVerificationCode(req);
                        logger.info("发送完毕, resp:{}", resp);
                    }else{
                        logger.info("switchVal != 1 不再重复告警!");
                    }
                } else {
                    logger.info("熔断策略暂无配置手机号，未发送短信通知！");
                }
            } else {
                logger.info("熔断策略暂无配置手机号全局变量，未发送短信通知！");
            }
        }else {
            logger.info("mobileKey未设置，无法通知 !");
        }
    }
}
